
package com.ds.listener;

import com.ds.client.JDSSessionFactory;
import com.ds.common.JDSConstants;
import com.ds.common.JDSException;
import com.ds.common.logging.Log;
import com.ds.common.logging.LogFactory;
import com.ds.common.query.*;
import com.ds.context.JDSActionContext;
import com.ds.engine.ConnectInfo;
import com.ds.engine.JDSSessionHandle;
import com.ds.home.EIDevice;
import com.ds.home.engine.GWEngine;
import com.ds.home.engine.HomeEventControl;
import com.ds.home.event.DeviceEvent;
import com.ds.home.query.IOTConditionKey;
import com.ds.iot.Device;
import com.ds.iot.HomeException;
import com.ds.iot.ct.CtIotFactory;
import com.ds.iot.enums.DeviceEventEnums;
import com.ds.iot.enums.DeviceStatus;
import com.ds.org.Person;
import com.ds.server.JDSServer;
import com.ds.server.OrgManagerFactory;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class CheckOnLineTask implements Runnable {

    private static final Log logger = LogFactory.getLog(JDSConstants.CONFIG_KEY, com.ds.server.ClearSessionCheckTask.class);
    private final String factoryName;

    public CheckOnLineTask(String factoryName) {
        this.factoryName = factoryName;
    }


    public void run() {
        try {
            if (JDSServer.getInstance().started()) {
                Condition<IOTConditionKey, JLuceneIndex> condition = new Condition<>(IOTConditionKey.DEVICE_STATES, Operator.NOT_EQUAL, DeviceStatus.DELETE.getCode());
                if (factoryName != null && !factoryName.equals("")) {
                    Condition factoryCondition = new Condition<IOTConditionKey, JLuceneIndex>(IOTConditionKey.DEVICE_FACTORY, Operator.EQUALS, factoryName);
                    condition.addCondition(factoryCondition, JoinOperator.JOIN_AND);
                }
                Condition<IOTConditionKey, JLuceneIndex> typecondition = new Condition<>(IOTConditionKey.DEVICE_DEVICETYPE, Operator.EQUALS, 0);
                condition.addCondition(typecondition, JoinOperator.JOIN_AND);


                Condition endcondition = new Condition(IOTConditionKey.DEVICE_LASTLOGINTIME,
                        Operator.GREATER_THAN, (System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000 )));
                condition.addCondition(endcondition, JoinOperator.JOIN_AND);


                Order order = new Order(IOTConditionKey.DEVICE_LASTLOGINTIME, false);
                condition.addOrderBy(order);

                Set<String> deviceIds = GWEngine.getDefaultEngine().findDevice(condition).get();

                for (String deviceId : deviceIds) {
                    EIDevice device = GWEngine.getDefaultEngine().getDeviceById(deviceId);

                    Person person = OrgManagerFactory.getOrgManager().getPersonByAccount(device.getBindingaccount());
                    ConnectInfo con = new ConnectInfo(person.getID(), person.getAccount(), person.getPassword());
                    Set<JDSSessionHandle> handles = JDSServer.getInstance().getSessionHandleList(con);



                    if (handles.size() > 0) {
                        for (JDSSessionHandle handle : handles) {
                            String sysCode = JDSServer.getSessionhandleSystemCodeCache().get(handle);
                            device.setLastlogintime(System.currentTimeMillis());
                            device.setStates(DeviceStatus.ONLINE.getCode());

                            if (device.getStates().equals(DeviceStatus.OFFLINE.getCode())) {
                                fireDeviceEvent(CtIotFactory.getCtIotService().getDeviceById(device.getDeviceid()), DeviceEventEnums.onLine);
                            }

                            GWEngine.getDefaultEngine().updateDevice(device);
                        }
                    } else {

                        if (device.getStates().equals(DeviceStatus.ONLINE.getCode())) {
                            device.setStates(DeviceStatus.OFFLINE.getCode());
                        fireDeviceEvent(CtIotFactory.getCtIotService().getDeviceById(device.getDeviceid()), DeviceEventEnums.offLine);
                        GWEngine.getDefaultEngine().updateDevice(device);
                    }

                    }

                }


            }
        } catch (Exception bpme) {
            logger.error("Get WorkflowServer instance failed.", bpme);
        }

    }


    private void fireDeviceEvent(final Device device, final DeviceEventEnums eventID) throws HomeException {
        if (device != null) {
            fireDeviceEvent(device, eventID, null);
        }

    }


    private void fireDeviceEvent(final Device device, final DeviceEventEnums eventID, Map eventContext) throws HomeException {

        final DeviceEvent event = new DeviceEvent(device, null, eventID, null);
        event.setContextMap(eventContext);
        new Thread() {
            @Override
            public void run() {
                try {
                    HomeEventControl.getInstance().dispatchEvent(event);
                } catch (JDSException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

}
